﻿using System;
using System.Collections.Generic;
using System.Linq;
using Sustainalytics.Reporting.Framework;
using Foxit.PDF.PageElements;
using Foxit.PDF;
using Foxit.PDF.Imaging;
using Sustainalytics.Entities.RiskRatings;
using Image = Foxit.PDF.PageElements.Image;
using Sustainalytics.RiskRatings.Reporting.Charts;
using Sustainalytics.Entities;

namespace Sustainalytics.RiskRatings.Reporting
{
    public class CompanyOverviewSection : PdfReportSectionGenerator
    {
        public CompanyOverviewSection(int index):base(index)        {
            this._reportSection.Name = "Company overview section";
        }
        public override void ComposeSectionContent()
        {
            isCoreReport = _dataSource.ReportType == ReportType.CoreRiskRatingsReport || _dataSource.ReportType == ReportType.SummaryCoreRiskRatingsReport;
            var columnWidth = (_report.PageMaxWidth - (float)HorisontalSpacing.Large) / 2;
            PdfReportPage page;
            if (isCoreReport)
                page = new PdfReportPage_Core(_report, _dataSource, 1);
            else
                page = new PdfReportPage_RiskRatingOverview(_report, _dataSource, false);
            _report.Pages.Add(page);
            float currentYOffset = page.Top + (float)VerticalSpacing.Small;
            var currentXOffset = 130f;
            OutlinePositions.Add(new OutlinePosition { Name = "Rating Overview", PageNumber = OutlinePageCount, VerticalPosition = page.Top - HeaderHeight });
            
            currentYOffset = AddAnalystView(page, currentXOffset, currentYOffset, columnWidth);

            var top = AddRiskRatingDistribution(page, 0f, currentYOffset, columnWidth);
            AddRelativePerformance(page, columnWidth, currentYOffset, columnWidth);
            if (isCoreReport)
            {
                currentYOffset = AddRiskAnalisys(page, 0f, top);
                AddRiskDetailsChart(page, currentYOffset);
            }
            else
            {
                var left = _report.PageMaxWidth / 2;
                var chartWidth = (page.Dimensions.Width - (float)HorisontalSpacing.Large) / 3;
                AddBubbleChart(page, left + 40f, top + 20f, chartWidth);

                left = _report.PageMaxWidth / 2;
                page.Elements.Add(new Circle(left + 30f, top + chartWidth + 15f, 6f, 6f, new RgbColor(231, 235, 186), RgbColor.White, 0.5f, LineStyle.Solid));
                page.Elements.Add(new Label("Circle size = Contribution to ESG Risk Rating", left + 45f, top + chartWidth + 12f, 200f,
                    6f + 2f, Fonts.RobotoRegular, 6f, TextAlign.Left, RgbColor.Black));

                top = AddAttributionAnalisys(page, 0f, top, _report.PageMaxWidth);

                top += 5f;

                var legend = AddLegend(0f, top);
                page.Elements.Add(legend);

                top += 35f;
                AddRiskAnalisys(page, 0f, top);
            }
        }

        private void AddBubbleChart(PdfReportPage page, float x, float y, float maxWidth)
        {
            var issues = _dataSource.MaterialIssuesOverview
                .OrderByDescending(item => ((MaterialIssueType)item.Type) == MaterialIssueType.BaselineIssue)
                .ThenByDescending(item => item.FinalWeight)
                .Take(6);

            RiskRating_BubbleChart chartObj = new RiskRating_BubbleChart(x, y, maxWidth);
            chartObj.MaterialIssueDataPoints = issues.ToList();
            page.Elements.Add(chartObj);
        }

        private float AddRiskRatingDistribution(PdfReportPage page, float x, float y, float maxWidth)
        {
            float currentYOffset = y;
                        
            page.Elements.Add(new Label("ESG Risk Rating Distribution", x, currentYOffset, maxWidth, 11f, Fonts.RobotoBold, 8.5f, TextAlign.Left, RgbColor.Black));
            currentYOffset += 5;

            RiskRating_CustomColumnChartGroup chartObj = new RiskRating_CustomColumnChartGroup();
            chartObj.Left = x;
            chartObj.Top = currentYOffset;
            chartObj.Width = maxWidth;
            chartObj.Height = 170;
            chartObj.RiskRatingClusterList = _dataSource.OverallClusters;
            chartObj.UniverseChartValues = _dataSource.UniverseAggregateDataPoints.Data;
            chartObj.IndustryChartValues = _dataSource.IndustryAggregateDataPoints.Data;
            chartObj.SubIndustryChartValues = _dataSource.SubIndustryAggregateDataPoints.Data;
            chartObj.Assessment = _dataSource.CompanyProfile.Assessment.ToString(); 

            page.Elements.Add(chartObj);
            currentYOffset += 140;

            return currentYOffset;
        }

        private void AddRelativePerformance(PdfReportPage page, float left, float top, float maxWidth)
        {
            left += (float)HorisontalSpacing.Large;

            page.Elements.Add(new Label("Relative Performance", left, top, maxWidth, 11f, Fonts.RobotoBold, 8.5f, TextAlign.Left, RgbColor.Black));
            top += 15;

            Table benchmarkTable = GetDefaultTable(left, top, maxWidth, 100);
            benchmarkTable.CellDefault.Border.Bottom.LineStyle = LineStyle.Dots;
            benchmarkTable.CellDefault.Border.Bottom.Width = 0.5f;
            benchmarkTable.CellDefault.Border.Color = RgbColor.Gray;
            benchmarkTable.CellDefault.VAlign = VAlign.Center;
            benchmarkTable.Columns.Add(maxWidth * 0.05f);
            benchmarkTable.Columns.Add(maxWidth * 0.45f);
            benchmarkTable.Columns.Add(maxWidth * 0.25f);
            benchmarkTable.Columns.Add(maxWidth * 0.25f);

            var row = benchmarkTable.Rows.Add(10);
            row.CellDefault.VAlign = VAlign.Center;
            row.Cells.Add(string.Empty);
            row.Cells.Add(string.Empty);
            row.Cells.Add("Rank", Fonts.RobotoBold, 7f);
            row.Cells.Add("Percentile", Fonts.RobotoBold, 7f);
            row.CellDefault.Border.Bottom.LineStyle = LineStyle.None;

            row = benchmarkTable.Rows.Add(10);
            row.CellDefault.VAlign = VAlign.Top;
            row.Cells.Add(string.Empty);
            row.Cells.Add(string.Empty);
            row.Cells.Add(new FormattedTextArea($"<p>(1<sup><font size='0'>st</font></sup> = lowest risk)</p>",
                0f, 0f, 60, 9f, Fonts.RobotoFontFamily, 7f, false));
            row.Cells.Add(new FormattedTextArea($"<p>(1<sup><font size='0'>st</font></sup> = lowest risk)</p>",
                0f, 0f, 60, 9f, Fonts.RobotoFontFamily, 7f, false));

            int percentile = 0;


            row = benchmarkTable.Rows.Add(20f);

            row.Cells.Add(new Rectangle(0f, 0f, 10f, 10f, new RgbColor(204, 204, 204), new RgbColor(204, 204, 204)));
            row.Cells.Add(new Label("Global Universe", 5f, 0f, 100f, 7f, Fonts.RobotoRegular, 7f, TextAlign.Left, RgbColor.Black));
            row.Cells.Add(new FormattedTextArea(string.Format("<b>{0}</b> out of {1}",
                _dataSource.Benchmark.CompanyBenchmark.UniversePerformanceRisk.Rank.ToString(),
                _dataSource.Benchmark.CompanyBenchmark.UniversePerformanceRisk.Count.ToString()),
                0f, 0f, maxWidth * 0.25f, 9f, Fonts.RobotoFontFamily, 7f, false));

            if (int.TryParse(Math.Round(_dataSource.Benchmark.CompanyBenchmark.UniversePerformanceRisk.Percentile * 100, 0, MidpointRounding.AwayFromZero).ToString(), out percentile))
                row.Cells.Add(ReportHelper.AddOrdinal(percentile), Fonts.RobotoBold, 7f);
            else
                row.Cells.Add("N/A", Fonts.RobotoBold, 7f);


            row = benchmarkTable.Rows.Add(20f);

            row.Cells.Add(new Rectangle(0f, 0f, 10f, 10f, new RgbColor(142, 175, 200), new RgbColor(142, 175, 200)));
            var industryName = _dataSource.CompanyProfile.PeerGroup + " (Industry Group)";
            var industryNameLenght = Fonts.RobotoRegular.GetTextWidth(industryName, 7);
            if (industryNameLenght > 100)
            {
                row.Cells.Add(new TextArea(industryName, 5f, 1f, 100f, 20f, Fonts.RobotoRegular, 7f, TextAlign.Left, RgbColor.Black));
            }
            else
            {
                row.Cells.Add(new Label(industryName, 5f, 0f, 100f, 9f, Fonts.RobotoRegular, 7f, TextAlign.Left, RgbColor.Black));
            }
            row.Cells.Add(new FormattedTextArea(string.Format("<b>{0}</b> out of {1}",
                _dataSource.Benchmark.CompanyBenchmark.IndustryPerformanceRisk.Rank.ToString(),
                _dataSource.Benchmark.CompanyBenchmark.IndustryPerformanceRisk.Count.ToString()),
                0f, 0f, maxWidth * 0.25f, 9f, Fonts.RobotoFontFamily, 7f, false));

            if (int.TryParse(Math.Round(_dataSource.Benchmark.CompanyBenchmark.IndustryPerformanceRisk.Percentile * 100, 0, MidpointRounding.AwayFromZero).ToString(), out percentile))
                row.Cells.Add(ReportHelper.AddOrdinal(percentile), Fonts.RobotoBold, 7f);
            else
                row.Cells.Add("N/A", Fonts.RobotoBold, 7f);

            page.Elements.Add(benchmarkTable);


            row = benchmarkTable.Rows.Add(20f);

            row.Cells.Add(new Rectangle(0f, 0f, 10f, 10f, new RgbColor(29, 96, 143), new RgbColor(29, 96, 143)));

            var subIndustryName = _dataSource.CompanyProfile.SubPeerGroup + " (Subindustry)";
            var subIndustryNameLenght = Fonts.RobotoRegular.GetTextWidth(subIndustryName, 7);
            if (subIndustryNameLenght > 100)
            {
                row.Cells.Add(new TextArea(subIndustryName, 5f, 1f, 100f, 20f, Fonts.RobotoRegular, 7f, TextAlign.Left, RgbColor.Black));
            }
            else
            {
                row.Cells.Add(new Label(subIndustryName, 5f, 0f, 100f, 9f, Fonts.RobotoRegular, 7f, TextAlign.Left, RgbColor.Black));
            }
            row.Cells.Add(new FormattedTextArea(string.Format("<b>{0}</b> out of {1}",
                _dataSource.Benchmark.CompanyBenchmark.SubIndustryPerformanceRisk.Rank.ToString(),
                _dataSource.Benchmark.CompanyBenchmark.SubIndustryPerformanceRisk.Count.ToString()),
                0f, 0f, maxWidth * 0.25f, 9f, Fonts.RobotoFontFamily, 7f, false));

            if (int.TryParse(Math.Round(_dataSource.Benchmark.CompanyBenchmark.SubIndustryPerformanceRisk.Percentile * 100, 0, MidpointRounding.AwayFromZero).ToString(), out percentile))
                row.Cells.Add(ReportHelper.AddOrdinal(percentile), Fonts.RobotoBold, 7f);
            else
                row.Cells.Add("N/A", Fonts.RobotoBold, 7f);

            page.Elements.Add(benchmarkTable);
        }

        private float AddAnalystView(PdfReportPage page, float left, float top, float maxWidth)
        {
            page.Elements.Add(new Line(0f, top, _report.PageMaxWidth, top, 2, RgbColor.Black));
            float currentYOffset = top + 20f;
            page.Elements.Add(new Label("Rating Overview", 0f, currentYOffset, left, 11, Fonts.MontserratRegular, 11f, TextAlign.Left, RgbColor.Black));

            string overviewText = string.Empty;
            if (isCoreReport)
                overviewText = _dataSource.CoreCompanyProfile.Sentences.First(sentence => sentence.Key == 6).Value.Value;
            else
            {
                if (_dataSource.CompanyProfile.AnalystViewOverallAssessment != null && _dataSource.CompanyProfile.AnalystViewOverallAssessment.Value != null)
                {
                    overviewText = _dataSource.CompanyProfile.AnalystViewOverallAssessment.Value;
                }
                else
                {
                    overviewText = $"{_dataSource.CompanyProfile.CompanyName} unmanaged risks driven by ESG factors are assessed as {_dataSource.CompanyProfile.Assessment} considering that the company has been implicated in several significant ESG-related controversies, its hight exposure combined with an average management of material ESG issues.";
                }
            }
            if (!String.IsNullOrEmpty(overviewText))
            {
                var height = 50f;
                if (overviewText.Length > 290)
                    height = 60f;
                if (overviewText.Length > 350)
                    height = 70f;
                left = left - 20;
                var fontsize = 9f;
                if (overviewText.Length > 500)
                    fontsize = 7.5f;
                if (overviewText.Length > 400 && overviewText.Length < 500)
                    fontsize = 8f;
                else if (overviewText.Length > 350 && overviewText.Length < 400)
                    fontsize = 8.5f;
                var style = new FormattedTextAreaStyle(Fonts.RobotoFontFamily, fontsize, false)
                {
                    Paragraph = { Align = TextAlign.Justify, Indent = 0, SpacingAfter = 0, AllowOrphanLines = false, PreserveWhiteSpace = false }
                };

                var textArea = new FormattedTextArea(overviewText, left-5f, currentYOffset + 3.5f, _report.PageMaxWidth-left, height+5f, style);
                page.Elements.Add(new Rectangle(left-15f, currentYOffset, _report.PageMaxWidth-left +15f, 60f,
                    new RgbColor(235, 241, 246), new RgbColor(235, 241, 246), 1f, LineStyle.Solid));
                page.Elements.Add(textArea);
            }
            currentYOffset += 65;
            return currentYOffset;
        }

        private float AddAttributionAnalisys(PdfReportPage page, float left, float top, float maxWidth)
        {
            var image = ReportHelper.GetFile("icon-attribution.png");

            page.Elements.Add(new Image(ImageData.GetImage(image), left, top - 5f, 0.2f));
            page.Elements.Add(new Label("Attribution Analysis", left + 25f, top, maxWidth, 9, Fonts.MontserratBold, 9, TextAlign.Left, RgbColor.Black));

            page.Elements.Add(new Line(left + 150f, top + 5f, maxWidth, top + 5f, 2, RgbColor.Black));

            top += 25f;


            const float headerFontSize = 6f;
            const float headerRowHeight = 8f;
            const float rowHeight = 20f;


            var style = new FormattedTextAreaStyle(Fonts.RobotoFontFamily, 7f, false)
            {
                Paragraph = { Align = TextAlign.Left, Indent = 0, SpacingAfter = 0, AllowOrphanLines = false, PreserveWhiteSpace = true }
            };


            if (_dataSource.MaterialIssuesOverview == null || _dataSource.MaterialIssuesOverview.Count == 0) return top;

            var columns = new[] { 0.0f, 20f, 15f, 105f, 30f, 110f };

            var tableWidth = _report.PageMaxWidth + 5;
            var tableHeight = _report.PageMaxHeight - top;

            
            var table = new Table(left, top, tableWidth, tableHeight);
            table.Border.Width = 0.0f;
            table.Border.Color = Grayscale.Black;
            table.Border.LineStyle = LineStyle.None;
            table.BackgroundColor = RgbColor.White;
            table.CellSpacing = 0.0f;
            table.CellDefault.Align = TextAlign.Center;
            table.CellDefault.VAlign = VAlign.Center;
            table.CellDefault.Padding.Value = 0.0f;
            table.CellDefault.Border.Width = 0.2f;
            table.CellDefault.Border.LineStyle = LineStyle.None;
            table.CellDefault.Border.Color = RgbColor.Black;

            table.Columns.Add(columns[1]);
            table.Columns.Add(columns[2]);
            table.Columns.Add(columns[3]);
            table.Columns.Add(columns[4]);
            table.Columns.Add(columns[5]);

            var row = table.Rows.Add(headerRowHeight);
            row.CellDefault.VAlign = VAlign.Top;
            row.Cells.Add(string.Empty);
            row.Cells.Add(string.Empty);
            row.Cells.Add(string.Empty);
            row.Cells.Add(string.Empty);
            row.Cells.Add(new Label("ESG Risk Rating", 0.0f, 0.0f, columns[5],
                headerFontSize + 2, Fonts.RobotoRegular, headerFontSize, TextAlign.Left, RgbColor.Black));

            row = table.Rows.Add(headerRowHeight);
            row.CellDefault.VAlign = VAlign.Top;
            row.CellDefault.Align = TextAlign.Left;
            row.Cells.Add(new Label("Top Material Issues", 0.0f, 0.0f, 100f,
                headerFontSize + 2, Fonts.RobotoRegular, headerFontSize, TextAlign.Left, RgbColor.Black), 3);
            row.Cells.Add(new Label("Score", 0.0f, 0.0f, columns[4],
                headerFontSize + 2, Fonts.RobotoRegular, headerFontSize, TextAlign.Center, RgbColor.Black));
            row.Cells.Add(new Label("  Negl     Low     Med      High    Severe", 0.0f, 0.0f, columns[5],
                headerFontSize + 2, Fonts.RobotoRegular, headerFontSize, TextAlign.Left, RgbColor.Black));

            row = table.Rows.Add(headerRowHeight + 10f);
            row.CellDefault.VAlign = VAlign.Top;
            row.Cells.Add(string.Empty);
            row.Cells.Add(string.Empty);
            row.Cells.Add(string.Empty);
            row.Cells.Add(string.Empty);
            row.Cells.Add(new Label("    0-2      2 - 4     4 - 6      6 - 8     8 - 20+", 0.0f, 0.0f, columns[5],
                headerFontSize + 2, Fonts.RobotoRegular, headerFontSize, TextAlign.Left, RgbColor.Black));

            var tableCellCurrentY = top + 48;
            var index = 1;

            foreach (var mei in _dataSource.MaterialIssuesOverview.OrderByDescending(x => ((MaterialIssueType)x.Type) == MaterialIssueType.BaselineIssue).ThenByDescending(x => x.FinalWeight).Take(6))
            {

                var meiIndex = $"<p><Font Color='#D3D3D3'>{index}</Font></p>";
                var meiName = $"<p>{mei.Name}</p>";
                var formattedTextArea = new FormattedTextArea(meiName, 0f, 0f, columns[3], rowHeight, style);
                var requiredHeight = formattedTextArea.GetRequiredHeight();

                PageElementPositions.Add(new PageElementPosition
                {
                    Name = mei.Name,
                    PageNumber = 1,
                    HorizontalPosition = left + 20,
                    VerticalPosition = tableCellCurrentY,
                    Width = 130,
                    Height = requiredHeight,
                });
                tableCellCurrentY += rowHeight;

                row = table.Rows.Add(rowHeight);

                if (mei.EventIndicators.Any())
                {
                    var maxAnswerCategory = mei.EventIndicators.Max(ei => ei.AnswerCategory);
                    var answerCategoryImage = GetAnswerCategoryImage(0f, 5f, maxAnswerCategory);

                    row.Cells.Add(answerCategoryImage);
                }
                else
                {
                    row.Cells.Add(string.Empty);
                }

                var cell = row.Cells.Add(new FormattedTextArea(meiIndex, 0f, 0f, columns[2], requiredHeight, style));
                cell.Align = TextAlign.Left;
                cell = row.Cells.Add(new FormattedTextArea(meiName, 0f, 0f, columns[3], requiredHeight, style));
                cell.Align = TextAlign.Left;

                row.Cells.Add(new Label((mei.UnmanagedRisk).ToString("#0.0"), 0f, 7f, columns[4],
                    rowHeight, Fonts.RobotoRegular, headerFontSize, TextAlign.Center, RgbColor.Black));

                var assesmentImage = GetAssessmentChart(0f, 3f, mei.UnmanagedRisk, mei.Assessment.ToString());

                row.Cells.Add(assesmentImage);

                index++;
            }

            page.Elements.Add(table);

            tableHeight = table.GetRequiredHeight();

            top += tableHeight + 10f;

            //var legend = GetSignificantEventLegend(left, top);

            //page.Elements.Add(legend);

            //top += 30f;

            return top;
        }


        private Group GetAnswerCategoryImage(float left, float top, int answerCategory)
        {
            var imageHeight = 10f;
            var group = new Group();

            var path = new Path(left + 5f, top, new RgbColor(242, 122, 53), new RgbColor(242, 122, 53), 1, LineStyle.Solid, true);
            path.SubPaths.Add(new LineSubPath(left, top + 9f));
            path.SubPaths.Add(new LineSubPath(left + 10f, top + 9f));
            group.Add(path);

            group.Add(new Label(answerCategory.ToString(), left, top + 2.5f, imageHeight,
                imageHeight, Fonts.RobotoBold, 6f, TextAlign.Center, RgbColor.White));

            return group;
        }

        private Group AddLegend(float left, float top)
        {
            var group = new Group();

            var path = new Path(left + 5f, top, RgbColor.Gray, RgbColor.White, 0.5f, LineStyle.Solid, true);
            path.SubPaths.Add(new LineSubPath(left, top + 9f));
            path.SubPaths.Add(new LineSubPath(left + 10f, top + 9f));
            group.Add(path);

            group.Add(new Label("= Significant event", left + 20f, top + 2f, 100f,
                8f, Fonts.RobotoRegular, 6f, TextAlign.Left, RgbColor.Black));

            
            return group;
        }


        private Group GetAssessmentChart(float left, float top, double unmanagedRisk, string assessment)
        {
            var assessmentWidth = 20f;

            float currentYOffset = top + 2f;
            float startingPos = left;

            Dictionary<string, RgbColor> assessmentColors = new Dictionary<string, RgbColor>()
            {
                {"X",  new RgbColor(204, 204, 204)},
                {"A",  new RgbColor(248, 221, 152)},
                {"B",  new RgbColor(245, 204, 102)},
                {"C",  new RgbColor(242, 188, 50)},
                {"D",  new RgbColor(240, 171, 0)}
            };

            var score = Math.Round(unmanagedRisk, 1);


            var group = new Group();

            foreach (var cluster in _dataSource.OverallClusters)
            {
                    group.Add(new Rectangle(startingPos, currentYOffset, assessmentWidth, 8f,
                        assessmentColors[cluster.Code], assessmentColors[cluster.Code]));

                startingPos += assessmentWidth;
            }

            startingPos = left;

            foreach (var cluster in _dataSource.OverallClusters)
            {
                if (cluster.Assessment.ToString() == assessment)
                {
                    group.Add(new Rectangle(startingPos, currentYOffset, assessmentWidth, 8f,
                        RgbColor.Black, assessmentColors[cluster.Code], 1f));
                }

                startingPos += assessmentWidth;
            }

            startingPos = left;

            foreach (var cluster in _dataSource.MaterialIssuesClusters)
            {
                if (cluster.Assessment.ToString() == assessment)
                {
                    var boundDiff = cluster.UpperBound - cluster.LowerBound;
                    var scoreDiff = score - cluster.LowerBound;


                    var unit = assessmentWidth / boundDiff;

                    var increment = 0f;

                    if (score > cluster.UpperBound)
                    {
                        increment = (float)(unit * boundDiff);
                    }
                    else if (score > cluster.LowerBound && score <= cluster.UpperBound)
                    {
                        increment = (float)(unit * scoreDiff);
                    }

                    startingPos += increment;

                    var path = new Path(startingPos, currentYOffset - 2f, RgbColor.Black, RgbColor.Black, 1, LineStyle.Solid, true);
                    path.SubPaths.Add(new LineSubPath(startingPos - 3f, currentYOffset - 7f));
                    path.SubPaths.Add(new LineSubPath(startingPos + 3f, currentYOffset - 7f));
                    group.Add(path);
                }
                else
                {
                    startingPos += assessmentWidth;
                }
            }

            return group;
        }

        private void AddExposurePerManagementScatterChart(PdfReportPage page, float left, float top, float width, float height)
        {

            var pageElements = new Group();
            var leftOffset = 25.0f;
            var lineSize = 0.5f;
            var lineColor = RgbColor.Gray;
            var labelSize = 6f;
            var pointColor = new RgbColor(231, 235, 186);



            float chartWidth = (width - leftOffset);
            float chartHeight = height;
            float chartRootPointX = left + leftOffset;
            float chartRootPointY = top + chartHeight;



            // X Axis
            pageElements.Add(new Line(chartRootPointX, top, chartRootPointX, top + chartHeight, lineSize, lineColor));
            pageElements.Add(new Line(chartRootPointX + chartWidth, top, chartRootPointX + chartWidth, top + chartHeight, lineSize, lineColor));

            // Y Axis

            pageElements.Add(new Line(chartRootPointX, chartRootPointY, 
                chartRootPointX + chartWidth, chartRootPointY, lineSize, lineColor));
            pageElements.Add(new Line(chartRootPointX + 0.5f, chartRootPointY - chartHeight, 
                chartRootPointX + chartWidth - 0.5f, chartRootPointY - chartHeight, lineSize, lineColor));


            if (_dataSource.MaterialIssuesOverview == null || _dataSource.MaterialIssuesOverview.Count == 0) return;

            var issues = _dataSource.MaterialIssuesOverview
                .OrderByDescending(x => ((MaterialIssueType)x.Type) == MaterialIssueType.BaselineIssue)
                .ThenByDescending(x => x.FinalWeight)
                .Take(6);



            
            var xUnit = chartWidth / 100;
            var yUnit = chartHeight / 20;


            foreach (var issue in issues)
            {
                var circleRadius = (float)(issue.FinalWeight * 100);
                if (circleRadius > 30)
                    circleRadius = 30f;

                var x = chartRootPointX + ((100-(float)issue.Management) * xUnit);
                var y = chartRootPointY - ((float)issue.Exposure * yUnit);

                pageElements.Add(new Circle(x, y, circleRadius, circleRadius, pointColor, RgbColor.White, 0.5f, LineStyle.Solid));
            }

            var index = 1;
            foreach (var issue in issues)
            {
                var circleRadius = 1f;

                var x = chartRootPointX + ((100 - (float)issue.Management) * xUnit);
                var y = chartRootPointY - ((float)issue.Exposure * yUnit);

                //pageElements.Add(new Circle(x, y, circleRadius, circleRadius, RgbColor.Black, RgbColor.Black, 0.5f, LineStyle.Solid));
                pageElements.Add(new Label(index.ToString(), x - (labelSize / 2f) - 1f, y - 4f, labelSize + 2f,
                    labelSize + 2f, Fonts.RobotoRegular, labelSize, TextAlign.Center, RgbColor.Black));

                index++;
            }


            pageElements.Add(new Label("Strong", chartRootPointX, top + chartHeight + 3f, 30f,
                labelSize + 2f, Fonts.RobotoRegular, labelSize, TextAlign.Left, RgbColor.Black));

            pageElements.Add(new Label("Weak", chartRootPointX + chartWidth - 30f, top + chartHeight + 3f, 30f,
                labelSize + 2f, Fonts.RobotoRegular, labelSize, TextAlign.Right, RgbColor.Black));

            pageElements.Add(new Label("Management", left + leftOffset, chartRootPointY + 15f, chartWidth,
                labelSize + 3f, Fonts.RobotoBold, labelSize + 1f,
                TextAlign.Center, RgbColor.Black));
            pageElements.Add(new Label("Exposure", left, top + chartHeight, chartWidth,
                labelSize + 3f, Fonts.RobotoBold, labelSize + 1f, TextAlign.Center, RgbColor.Black)
            { Angle = -90 });

            pageElements.Add(new Label("Low", chartRootPointX - (labelSize + 5f), chartRootPointY, 30f,
                labelSize + 2f, Fonts.RobotoRegular, labelSize, TextAlign.Left, RgbColor.Black)
            { Angle = -90 });
            pageElements.Add(new Label("High", chartRootPointX - (labelSize + 5f), chartRootPointY - chartHeight + 30f, 30f,
                labelSize + 2f, Fonts.RobotoRegular, labelSize, TextAlign.Right, RgbColor.Black)
            { Angle = -90 });


            pageElements.Add(new Label("Negligible Risk", chartRootPointX + 10f, top + chartHeight - 12f, 50f,
                labelSize + 2f, Fonts.RobotoRegular, labelSize, TextAlign.Left, RgbColor.Black));
            pageElements.Add(new Label("Severe Risk", chartRootPointX + chartWidth - 37f, top + 5f, 50f,
                labelSize + 2f, Fonts.RobotoRegular, labelSize, TextAlign.Left, RgbColor.Black));




            page.AddElement(pageElements);

        }

        private void AddRiskDetailsChart(Page page, float top)
        {
            var currentYOffset = top + 20f;
            var columnWidth = (page.Dimensions.Width - (float)HorisontalSpacing.Large) / 3;
            currentYOffset += 50f;
            RiskRating_RiskRangeBarChart chartObj = new RiskRating_RiskRangeBarChart();
            chartObj.Left = 0f;
            chartObj.Top = currentYOffset;
            chartObj.Width = columnWidth;
            chartObj.Value1 = _dataSource.CompanyProfile.ManagementRisk.Exposure.Value;
            chartObj.Value2 = _dataSource.CompanyProfile.ManagementRisk.ManageableRisk.Value;
            chartObj.Value3 = _dataSource.CompanyProfile.ManagementRisk.ManagedRisk.Value;
            chartObj.Value4 = _dataSource.CompanyProfile.ManagementRisk.ManagementGap.Value;
            chartObj.Value5 = _dataSource.CompanyProfile.ManagementRisk.UnmanageableRisk.Value;
            chartObj.Value6 = _dataSource.CompanyProfile.ManagementRisk.UnmanagedRisk.Value;
            chartObj.BarHeight = 10f;
            chartObj.ChartType = RiskRangeChartType.OverallRiskDetails;
            page.Elements.Add(chartObj);
        }

        private float AddRiskAnalisys(PdfReportPage page, float left, float top)
        {
            var risk_analysis_image = ReportHelper.GetFile("icon-risk-analysis.png");
            float currentYOffset = top;
            page.Elements.Add(new Image(ImageData.GetImage(risk_analysis_image), left, top - 13f, 0.25f));
            page.Elements.Add(new Label("Risk Analysis", left + 30f, top - 7f, 100f, 12f, Fonts.MontserratBold, 10f, TextAlign.Left, RgbColor.Black));
            page.Elements.Add(new Line(left + 110f, top, _report.PageMaxWidth, top, 2, RgbColor.Black));
            var columnWidth = (_report.PageMaxWidth - 2 * (float)HorisontalSpacing.Medium) / 3;

            if (isCoreReport)
            {
                AddRiskAnalysisExposure(page, left, currentYOffset, columnWidth*2 + (float)HorisontalSpacing.Medium);
                currentYOffset += 100;
                AddRiskAnalysisManagement(page, left, currentYOffset, columnWidth * 2 + (float)HorisontalSpacing.Medium);
            }
            else
            {
                AddRiskAnalysisExposure(page, left, currentYOffset, columnWidth);
                AddRiskAnalysisManagement(page, left + columnWidth + (float)HorisontalSpacing.Medium, currentYOffset, columnWidth);
            }
            currentYOffset = AddRiskAnalysisScatterChart(page, 380, top + 40, _report.PageMaxWidth - 380);
            return currentYOffset;
        }

        float AddRiskAnalysisExposure(PdfReportPage page, float x, float y, float maxWidth)
        {
            float currentYOffset = y + (float)VerticalSpacing.Small + 10f;
            page.Elements.Add(new Label("Exposure Score", x + 3f, currentYOffset, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Black));
            currentYOffset += 15;
            var exposureScore = _dataSource.CompanyProfile.ManagementRisk.Exposure.Value.ToString("#0.0");
            var assesment = _dataSource.CompanyProfile.ExposureCluster.ToString();

            page.Elements.Add(new Label(exposureScore, x + 3f, currentYOffset+10f, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Black));
            page.Elements.Add(new Label(" /100", x + 18f, currentYOffset + 10f, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Gray));
            page.Elements.Add(new Label(assesment, x + 43f, currentYOffset+10f, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Black));

            RiskRating_RiskAnalysisRangeChart chartObjExposure = new RiskRating_RiskAnalysisRangeChart();
            chartObjExposure.Top = currentYOffset;
            chartObjExposure.Left = x + 80f;
            chartObjExposure.Width = 20f;
            chartObjExposure.Type = "Exposure";
            chartObjExposure.Value = (float)_dataSource.CompanyProfile.ManagementRisk.Exposure.Value;
            chartObjExposure.Assessment = assesment;
            chartObjExposure.SubIndustryValue = (float)_dataSource.CompanyProfile.SubIndustryExposureScore.Value;
            chartObjExposure.ExposureClusterList = _dataSource.ExposureClusters.Where(s => s.Type == RiskRatingClusterType.Overall).ToList();
            page.Elements.Add(chartObjExposure);
            currentYOffset += 30;

            if (isCoreReport)
            {
                page.Elements.Add(new Label(string.Format("Beta = {0}", _dataSource.CoreCompanyProfile.FinalBetaFactor.Value.ToString("#0.00")), x + 3f, currentYOffset, maxWidth, 6, Fonts.RobotoBold, 6, TextAlign.Left, RgbColor.Black));
                currentYOffset += 15;
            }
            else
            {
                page.Elements.Add(new Label(string.Format("Beta = {0}", _dataSource.CompanyProfile.OverallBetaFactor.Value.ToString("#0.00")), x + 3f, currentYOffset, maxWidth, 6, Fonts.RobotoBold, 6, TextAlign.Left, RgbColor.Black));
                currentYOffset += 15;

            }

            var style = new FormattedTextAreaStyle(Fonts.RobotoFontFamily, 6f, false)
            {
                Paragraph = { Align = TextAlign.Left, Indent = 0, SpacingAfter = 0, AllowOrphanLines = false }
            };
            string exposureText = string.Empty;

            if (isCoreReport)
            {
                exposureText = _dataSource.CoreCompanyProfile.Sentences.First(sentence => sentence.Key == 2).Value.Value;
            }
            else
            {
                if (_dataSource.CompanyProfile.ExposureComment != null && _dataSource.CompanyProfile.ExposureComment.Value != null)
                    exposureText = _dataSource.CompanyProfile.ExposureComment.Value;
                if (_dataSource.CompanyProfile.OverallExposureAssessment != null && _dataSource.CompanyProfile.OverallExposureAssessment.Value != null)
                    exposureText = exposureText  + _dataSource.CompanyProfile.OverallExposureAssessment.Value;
            }

            var formattedTextArea = new FormattedTextArea(exposureText, x + 3f, currentYOffset, maxWidth, 100f, style);
            var textAreaHeight = formattedTextArea.GetRequiredHeight();
            if (textAreaHeight + currentYOffset > _report.PageDimensions.Body.Height)
            {
                textAreaHeight = _report.PageDimensions.Body.Height - currentYOffset - 10f;
                page.Elements.Add(new Label("...", x + maxWidth+2f, currentYOffset + textAreaHeight - 13f, maxWidth, 8, Fonts.RobotoRegular, 6, TextAlign.Left, RgbColor.Black));
            }
            formattedTextArea = new FormattedTextArea(exposureText, x + 3f, currentYOffset, maxWidth, textAreaHeight, style);
            page.Elements.Add(formattedTextArea);

            currentYOffset += textAreaHeight + 10f;

            return currentYOffset;
        }

        float AddRiskAnalysisManagement(PdfReportPage page, float x, float y, float maxWidth)
        {

            float currentYOffset = y + (float)VerticalSpacing.Small + 10f;
            page.Elements.Add(new Label("Management Score", x , currentYOffset, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Black));
            currentYOffset += 15;

            var managementScore = _dataSource.CompanyProfile.ManagementRisk.Management.Value.ToString("#0.0");
            var managmentAssesment = _dataSource.CompanyProfile.ManagementCluster.ToString();

            page.Elements.Add(new Label(managementScore, x, currentYOffset+10f, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Black));
            page.Elements.Add(new Label(" /100", x+15f, currentYOffset + 10f, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Gray));
            page.Elements.Add(new Label(managmentAssesment, x + 43f, currentYOffset+10f, maxWidth, 10, Fonts.RobotoRegular, 8, TextAlign.Left, RgbColor.Black));

            RiskRating_RiskAnalysisRangeChart chartObjManagement = new RiskRating_RiskAnalysisRangeChart();
            chartObjManagement.Top = currentYOffset;
            chartObjManagement.Left = x + 80;
            chartObjManagement.Width = 20f;
            chartObjManagement.Type = "Management";
            chartObjManagement.Value = (float)_dataSource.CompanyProfile.ManagementRisk.Management.Value;
            chartObjManagement.Assessment = managmentAssesment;
            chartObjManagement.ManagementClusterList= _dataSource.ManagementClusters.Where(s => s.Type == RiskRatingClusterType.Overall).ToList();
            page.Elements.Add(chartObjManagement);

            currentYOffset += 30;

            var style = new FormattedTextAreaStyle(Fonts.RobotoFontFamily, 6f, false)
            {
                Paragraph = { Align = TextAlign.Left, Indent = 0, SpacingAfter = 0, AllowOrphanLines = false }
            };

            string managementText = String.Empty;
            if (isCoreReport)
            {
                managementText = _dataSource.CoreCompanyProfile.Sentences.First(sentence => sentence.Key == 3).Value.Value;
                managementText += " " + _dataSource.CoreCompanyProfile.Sentences.First(sentence => sentence.Key == 4).Value.Value;
                managementText += " " + _dataSource.CoreCompanyProfile.Sentences.First(sentence => sentence.Key == 5).Value.Value;
            }
            else
            {
                if (_dataSource.CompanyProfile.EsgRiskManagementComment != null && _dataSource.CompanyProfile.EsgRiskManagementComment.Value != null)
                    managementText = _dataSource.CompanyProfile.EsgRiskManagementComment.Value;
                if (_dataSource.CompanyProfile.OverallManagementAssessment != null && _dataSource.CompanyProfile.OverallManagementAssessment.Value != null)
                    managementText =managementText + _dataSource.CompanyProfile.OverallManagementAssessment.Value;
            }

            var formattedTextArea = new FormattedTextArea(managementText, x + 3f, currentYOffset, maxWidth, 500f, style);
            var textAreaHeight = formattedTextArea.GetRequiredHeight();

            if (textAreaHeight + currentYOffset > _report.PageDimensions.Body.Height)
            {
                textAreaHeight = _report.PageDimensions.Body.Height - currentYOffset - 10f;
                page.Elements.Add(new Label("...", x + maxWidth+2f, currentYOffset +textAreaHeight-13f, maxWidth, 8, Fonts.RobotoRegular, 6, TextAlign.Left, RgbColor.Black));
            }

            formattedTextArea = new FormattedTextArea(managementText, x + 3f, currentYOffset, maxWidth, textAreaHeight, style);
            page.Elements.Add(formattedTextArea);

            currentYOffset += textAreaHeight + 10f;

            return currentYOffset;

        }

        float AddRiskAnalysisScatterChart(PdfReportPage page, float x, float y, float maxWidth)
        {
            var chart = new RiskRating_ScatterChart(x, y, maxWidth)
            {
                SubPeerGroupBenchmark = _dataSource.Benchmark.CompanyBenchmark.PeersList,
                ShowGridLines = false,
                ChartType = ScatterChartType.Overview,
                CompanyId = _dataSource.CompanyId,
                SubIndustry = _dataSource.CompanyProfile.SubPeerGroup,
                SubIndustryDataPoints = _dataSource.SubIndustryRiskRatingPerformanceList,
                GlobalUniverseDataPoints = _dataSource.GlobalUniverseRiskRatingPerformanceList,
                RiskRatingClusterList = _dataSource.OverallClusters,
                SubIndustryAvgExposure =_dataSource.Benchmark.CompanyBenchmark.SubIndustryPerformanceExposure.Average,
                SubIndustryAvgManagement= _dataSource.Benchmark.CompanyBenchmark.SubIndustryPerformanceManagement.Average

            };
            page.Elements.Add(chart);
            return y + 150;
        }

        float AddRiskFramework(PdfReportPage page, float x, float y, float maxWidth)
        {
            float currentYOffset = y + (float)VerticalSpacing.Small;
            page.Elements.Add(new Label("Rating Overview".ToUpperInvariant(), x, currentYOffset, maxWidth, 11, Fonts.MontserratBold, 11, TextAlign.Left, RgbColor.Black));
            currentYOffset += 19;

            page.Elements.Add(new Label("Risk Framework".ToUpperInvariant(), x, currentYOffset, maxWidth, (float)TextSizes.SubSectionTitle, Fonts.MontserratRegular, (float)TextSizes.SubSectionTitle, TextAlign.Left, RgbColor.Black));
            currentYOffset += 19;

            RiskRating_RangeBarChart chartObj = new RiskRating_RangeBarChart();
            chartObj.Left = x + 20;
            chartObj.Top = currentYOffset;
            chartObj.Width = maxWidth - 20;
            chartObj.Value1 = (float)_dataSource.CompanyProfile.ManagementRisk.Exposure.Value;
            chartObj.Value2 = (float)_dataSource.CompanyProfile.ManagementRisk.ManagedRisk.Value;
            chartObj.Value3 = (float)_dataSource.CompanyProfile.ManagementRisk.UnmanagedRisk.Value;
            chartObj.BarHeight = 10f;
            chartObj.ChartType = RangeChartType.Overview_RiskFramework;
            page.Elements.Add(chartObj);
            currentYOffset += 55;

            /*
            string chartText = string.Empty;
            if (!string.IsNullOrWhiteSpace(_dataSource.CompanyProfile.EsgRiskManagementComment.Value))
                chartText = _dataSource.CompanyProfile.EsgRiskManagementComment.Value;

            FormattedTextArea textArea = new FormattedTextArea(chartText,
                                x,
                                currentYOffset,
                                maxWidth,
                                100,
                                Fonts.RobotoFontFamily, 6, false);

            page.Elements.Add(textArea);
            currentYOffset += textArea.GetRequiredHeight()+10;
            */

            page.Elements.Add(new Line(x, currentYOffset, x + maxWidth, currentYOffset, 1, Colors.LineColor));

            return currentYOffset;
        }

        float AddKeyIssues(PdfReportPage page, float x, float y, float maxWidth)
        {
            float currentYOffset = y + 8;
            float maxValueXAxis = 20;
            page.Elements.Add(new Label("Material Issues Snapshot".ToUpperInvariant(), x, currentYOffset, maxWidth, 9, Fonts.MontserratRegular, 9, TextAlign.Left, RgbColor.Black));
            currentYOffset += 17;

            page.Elements.Add(new Line(x, currentYOffset, x + 7, currentYOffset, 5, RgbColor.Black));
            page.Elements.Add(new Label("Unmanaged Risk", x + 10, currentYOffset - 4, 75, 7, Fonts.RobotoRegular, 7, TextAlign.Left, RgbColor.Black));
            page.Elements.Add(new Line(x + 90, currentYOffset, x + 97, currentYOffset, 5, new RgbColor(180, 213, 209)));
            page.Elements.Add(new Label("Issue Exposure", x + 100, currentYOffset - 4, 75, 7, Fonts.RobotoRegular, 7, TextAlign.Left, RgbColor.Black));

            currentYOffset += 20;

            float startingPos = x + maxWidth * 0.6f;
            float dotSize = maxWidth * 0.4f / maxValueXAxis;
            for (int i = 0; i <= maxValueXAxis; i++)
            {
                if (i % 5 == 0)
                {
                    page.Elements.Add(new Line(startingPos + i * dotSize,
                            currentYOffset - 5,
                            startingPos + i * dotSize,
                            currentYOffset,
                            1, RgbColor.Gray));
                    page.Elements.Add(new Label(i.ToString(),
                            startingPos + i * dotSize - 5,
                            currentYOffset - 14,
                            10,
                            7f, Fonts.RobotoRegular, 6f, TextAlign.Center, RgbColor.Black));
                }
            }

            page.Elements.Add(new Line(x, currentYOffset, x + maxWidth, currentYOffset, 0.5f, RgbColor.Gray, LineStyle.Dots));
            currentYOffset += 10;

            if (_dataSource.CompanyProfile.MaterialEsgIssues != null)
            {
                var sortedMeiList = _dataSource.CompanyProfile.MaterialEsgIssues.OrderByDescending(j => j.FinalWeight.Value).ToList();
                var baseline = sortedMeiList.Find(i => i.Type == MaterialIssueType.BaselineIssue);
                if (baseline != null)
                {
                    page.Elements.Add(AddIndicatorRow(baseline, x, currentYOffset, maxWidth, 40, maxValueXAxis, _dataSource.MaterialIssuesClusters));
                    currentYOffset += 40;
                }

                page.Elements.Add(new Label("Material Environmental and Social Issues", x, currentYOffset, 200, 7f, Fonts.RobotoRegular, 7f, TextAlign.Left, RgbColor.Black));
                currentYOffset += 15;
                page.Elements.Add(new Line(x, currentYOffset, x + maxWidth, currentYOffset, 0.5f, RgbColor.Gray, LineStyle.Dots));
                currentYOffset += 10;

                foreach (var indicator in sortedMeiList.Where(i => i.Type != MaterialIssueType.BaselineIssue).Take(3))
                {
                    page.Elements.Add(AddIndicatorRow(indicator, x, currentYOffset, maxWidth, 40, maxValueXAxis, _dataSource.MaterialIssuesClusters));
                    currentYOffset += 40;
                }
            }
            return currentYOffset;
        }

        Group AddIndicatorRow(RiskRatingMaterialEsgIssueBase indicator, float x, float y, float width, float height, float maxValueXAxis, List<RiskRatingCluster> MeiCluster)
        {
            Group root = new Group();
            float currentXOffset = x;
            root.Add(new Image(ImageData.GetImage(ReportHelper.GetMeiImage(indicator.ExternalId.ToString(),MeiImageColor.Black,MeiImageSize.Small)), currentXOffset, y - 5, 0.5f));
            currentXOffset += 0.1f * width;
            root.Add(new TextArea(indicator.Name, currentXOffset, y, 0.4f * width, 18, Fonts.RobotoRegular, 7, TextAlign.Left, RgbColor.Black));
            currentXOffset += 0.4f * width;
            root.Add(new Label(indicator.ManagementRisk.UnmanagedRisk.Value.ToString("0.0"), currentXOffset, y, 0.1f * width, 8, Fonts.RobotoBold, 7, TextAlign.Center, RgbColor.Black));
            currentXOffset += 0.1f * width;
            root.Add(GetBulletChart(indicator, currentXOffset, y, 0.4f * width, 20, maxValueXAxis));

            root.Add(new Label(string.Format("{0} Risk", indicator.Assessment), currentXOffset, y + 12, 100, 7, Fonts.RobotoRegular, 7, TextAlign.Left, RgbColor.Black));

            root.Add(new Line(x, y + 25, x + width, y + 25, 0.5f, RgbColor.Gray, LineStyle.Dots));
            return root;
        }

        BulletChart GetBulletChart(RiskRatingMaterialEsgIssueBase indicator, float x, float y, float width, float height, float maxValueXAxis)
        {
            BulletChart objChart = new BulletChart();
            objChart.Left = x;
            objChart.Top = y;
            objChart.MaxValueXAxis = maxValueXAxis;
            objChart.BarHeight = 10;
            objChart.Height = height;
            objChart.Value1 = (float)indicator.ManagementRisk.Exposure.Value;
            objChart.Value2 = (float)indicator.ManagementRisk.UnmanagedRisk.Value;
            objChart.Width = width;
            return objChart;
        }
    }
}
